


https://pandas.ac.cn/docs/reference/general_functions.html









import pandas as pd
import numpy as np

incomes = [20, 20, 25, 30, 35, 40, 45, 50, 50, 50]
df = pd.DataFrame({'Income': incomes})
# df 下所有方法：



# ---------------------------- 数据查看与基本信息 -----------------------------
df.head()
df.tail()
df.sample(n=5) # 随机抽取5行  frac=0.1-->10%的数据
df.columns.tolist() # 获取列名列表
df.index # 显示索引范围或标签
df.info()  # 输出列名、非空值数量、数据类型及内存使用  ---  显示数据概览
df.shape
df.dtypes
df.describe(include=None)  # 生成数值型列的统计摘要  默认None，只包含数值列
    #           Income
    # count  10.000000
    # mean   36.500000
    # std    12.258784
    # min    20.000000
    # 25%    26.250000
    # 50%    37.500000
    # 75%    48.750000
    # max    50.000000

    # include='all'：包含非数值列
    # include=['O']：仅文本列统计

    # 数值型        ----include=[np.number]----	count, mean, std, min, 分位数 (25%, 50%, 75%), max
    # 对象型	    ----include=['object']----count, unique, top (出现频率最高的值), freq (top值出现的频率)
    # 布尔型	    ----include=['bool']----count, unique, top, freq
    # 日期时间型	----include=['datetime']----count, min (最早日期), max (最晚日期), first (第一个日期), last (最后一个日期)
    # 分类型	    ----include=[填多个类型]----类似对象型，但会考虑分类顺序

    # 检查缺失值和唯一值情况
    desc = df.describe(include='all')
    print(desc.loc['count'])  # 非空值计数
    print(desc.loc['unique']) # 唯一值数量


df['age'].nunique() # 获取年龄的不同取值个数  相当于 group by age count(*)

# isna().sum() / isnull().sum()  输出各列缺失值总数
df.isnull().any() # 返回布尔值列表，表示所有行 或者 列 是否存在一个 为空的

df.memory_usage(deep=True) # 显示详细内存使用 查看每列内存占用（deep=True 计算对象类型真实内存）

df = df.convert_dtypes() # 优化内存;自动转换为更高效的数据类型（如 int64 → Int32） 不一定有用

# ---------------------------- 数据选择与过滤 -----------------------------
df["列"]
df.loc[['a', 'd'], ['Name', 'City']]
df.loc[['a', 'c']]
df.loc[:, 'Name']
df.loc['b':'d']  # 包含 'd' ; b c d
df.loc[(df['Age'] > 30) & (df['Score'] > 80)]
df.loc[df['City'] == 'NY', 'Age'] = 26
df.loc[:, 'Score'] = df.loc[:, 'Score'].apply(lambda x: x + 5) 

df.iloc[0]
df.iloc[:, 0]  # 第一列 ；   df.iloc[:, -1] 最后一列
df.iloc[1:3, :2]
df.iloc[1:4:2, 0:3:2]  # 行：1和3 (步长2)，列：0和2 (步长2)
col_mask = [True, False, True, False]  # 选取第1列和第3列
masked_cols = df.iloc[:, col_mask]
# 使用函数选择偶数位置的行
df.iloc[lambda x: [i for i in range(len(x)) if i % 2 == 0]]
# 随机选取3行
df.iloc[np.random.randint(0, len(df), size=3)]

# 快速标量访问
df.at['row_label', 'col_name']  # 比 loc 更快  但是只能处理单个元素
df.iat[0, 1]                    # 比 iloc 更快

df[~(df['col'] == 'X')]  # ~ | &

df.filter(items=['col1', 'col2'], like='_x', regex='^A')     # 指定列名 列名包含"_x"  列名以"A"开头

df.where(df > 0)  # 不满足条件的替换为NaN
df.mask(df > 0)   # 满足条件的替换为NaN

df.nsmallest(3, 'col')   # 'col'列最小的3行
df.nlargest(3, 'col')    # 'col'列最大的3行

df.truncate(before='2023-01-01', after='2023-12-31')   # 按索引范围截取

df[df[""] > 20]  #  布尔值
df[df['col'].notna()]    # 选择非缺失值



# query 和 evel 减少中间变量生成，提升效率
# 相较于传统的循环 或  df[df["A"] < 3] 这种语法效率提升10倍以上；适用 数据量大于1万的大数据集
# eval 适用 增加新列和修改原有列，含复杂函数
# query 适用 筛选，多条件组合
df.query("年龄 > 20 and 城市 == beijing")  # 复杂的表达式是用query和eval 利用字符串表达式来加速计算
df.eval("年龄 > 20 and 城市 == beijing")
df.loc[df['col'].isin(['A','B'])]  # 值在列表中
df['列A'].value_counts(normalize=False)  # 统计某列唯一值的频数或比例 相当于 groupby count


df[df.duplicated()]      # 标记重复的行
df.duplicated(subset=['col1','col2'], keep='first'/'last'/False)  # 标记重复行 返回布尔序列
df.drop_duplicates()     # 删除重复行

df.select_dtypes(include=['int64', 'float64'])  # 选择数值列
df.select_dtypes(exclude=['object'])           # 排除字符串列


# ---------------------------- 数据清洗与预处理 -----------------------------
df.dropna(axis=0/1, how='any'/'all'/*存在/全部缺失时删除*/, subset=['col']/*指定列判断*/, thresh=n/*保留至少 n 个非空值的行*/)
df.fillna(0)
df.fillna(method='ffill'/'bfill'/*向前/后填充*/)
df['col'].fillna(df['col'].mean())
df.drop_duplicates(subset=["A列"])
df.astype(np.int32)
df.replace({"旧值": "新值"})



# ---------------------------- 数据操作与转换 -----------------------------
df.assign(新列=df['列A']*2)   # 添加新列
df.drop('列名', axis=1)  # 删除行/列  此时如果 把 axis 换成 0，执行语句会找有没有  '列名'  这一行，如果找不到会报keyerror
# 删除列 → ​​axis=1​​
# 删除行 → ​​axis=0
df.rename(columns={'旧名':'新名'})  # 重命名列/索引
df.sort_values(by='列A', ascending=False)  # 按列值排序
df.sort_index() # 按索引排序
df['新列'] = df['列A'].apply(lambda x: x*2)    # 应用函数到行/列
df['状态列'] = df['状态列'].map({'Active':1})   # 值映射（Series专用）





# 文本清洗：
df['col'].str.lower()/upper()/title()  # ：大小写转换
df['col'].str.strip()/lstrip()/rstrip()  # ：去除空白
df['col'].str.replace('old','new')  # ：替换文本

# 分割与提取：
df['col'].str.split('/').str[0]  # ：分割取部分


df['col'].str.extract(r'(\d+)')   # ：提取​​符合正则表达式的​​子串​，返回 df 或 series
# 示例
s = pd.Series(["a1", "b2", "c3", "X-1a"], dtype="string")
result = s.str.extract(r"([a-z])(\d)")  # 两个捕获组：字母+数字  ，从开头匹配， 必须包含组（）
# s.str.extract(r"(?P<letter>[a-z])(?P<digit>\d)")   可以命名  第一列命名为 letter  第二列命名为 digit
#      0    1
# 0    a    1
# 1    b    2
# 2    c    3
# 3  NaN  NaN  # "X-1a" 未匹配字母+数字连续组合

# 验证数据格式（如身份证号/电话）	str.match()	df["ID"].str.match(r"^\d{17}[\dX]$")
# 拆分结构化文本（如日志/地址）	str.extract()	df["地址"].str.extract(r"(\d+号)")
# 同时需要检测和提取	先 match 过滤，再 extract	筛选后提取有效数据



# 过滤检测：
df['col'].str.contains('pattern')   # ：包含匹配
df['col'].str.match(r'^\d{3}')   # ：检查字符串​​是否从开头匹配​​正则表达式，返回布尔值 Series




# 时间解析
pd.to_datetime(df['date_str'], format='%Y-%m-%d')

# 时间属性提取
df['dt'].dt.year/month/day/hour
df['dt'].dt.day_name()   # ：星期名称

# 重采样
df.resample('D').mean()  # ：按天降采样
df.resample('H').ffill()  # ：按小时升采样填充




# ---------------------------- 数据分组与聚合 -----------------------------
grouped = df.groupby('城市') 
df.groupby('城市').agg({'销量':['sum','mean']})
pd.pivot_table(df, values='值', index='行', columns='列') 





# ---------------------------- 数据合并与连接 -----------------------------
pd.merge(df1, df2, on='键列')     # 非索引列
pd.concat([df1, df2], axis=0)    #（纵向堆叠）
df1.join(df2, how='left')        # 基于索引






# ---------------------------- 时间序列处理 -----------------------------
df['日期列'] = pd.to_datetime(df['日期列'])     # 转日期类型
df.resample('M').mean()   # （按月聚合） 时间重采样
df['滞后列'] = df['列A'].shift(1)      # 数据位移